home *** CD-ROM | disk | FTP | other *** search
/ ASME's Mechanical Engine…ing Toolkit 1997 December / ASME's Mechanical Engineering Toolkit 1997 December.iso / c_lang / z150_src.lzh / PORTABLE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1987-07-12  |  19.2 KB  |  677 lines

  1. #ifndef LINT
  2. static char sccsid[]="@(#) portable.c 1.5 87/05/03 16:01:05";
  3. #endif /* LINT */
  4.  
  5. #include "options.h"
  6. /*
  7. Copyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
  8. */
  9. /**********************
  10. portable.c contains functions needed to make Zoo portable to various
  11. implementations of C.
  12.  
  13. Note:  Provided a 2's complement machine is used, all functions in
  14. this file are themselves machine-independent and need not be changed
  15. when implementing Zoo on a different machine.  Some code will choke
  16. on 1's complement machines--I think.  
  17.  
  18. For machine-dependent declarations see files "machine.h" and "options.h". 
  19.  
  20. For machine-dependent functions see file "machine.c"
  21. */
  22.  
  23. /* See if we could just use these for MSC */
  24. #ifdef MSC
  25. #ifndef PORTABLE
  26. #define PORTABLE
  27. #endif
  28. #endif
  29.  
  30.  
  31. #ifdef PORTABLE
  32. #include <stdio.h>
  33. #include "various.h"
  34. #include "zoofns.h"
  35.  
  36. #include "machine.h"
  37. #include "zoo.h"
  38. #include "debug.h"
  39. #include "assert.h"
  40.  
  41. #ifdef NEEDCTYP
  42. #include <ctype.h>              /* for tolower() */
  43. #endif
  44.  
  45. #ifdef DEBUG
  46. extern int verbose;
  47. #endif
  48.  
  49. /* Functions defined for use within this file only.  */
  50. #ifdef LINT_ARGS
  51. long to_long (BYTE[]);
  52. int to_int (BYTE[]);
  53. void b_to_zooh(struct zoo_header *, BYTE[]);
  54. void b_to_dir(struct direntry *, BYTE[]);
  55. int dir_to_b(BYTE[], struct direntry *);
  56. void zooh_to_b(BYTE[], struct zoo_header *);
  57. void splitlong(BYTE[], long);
  58. void splitint(BYTE[], int);
  59. #else
  60. long to_long ();
  61. int to_int ();
  62. void b_to_zooh();
  63. void b_to_dir();
  64. int dir_to_b();
  65. void zooh_to_b();
  66. void splitlong();
  67. void splitint();
  68. #endif
  69.  
  70. extern unsigned int crccode;
  71.  
  72.  
  73. /************************************************************************/
  74. /*** Following are functions that make up for various implementations ***/
  75. /*** of C not having certain library routines.                        ***/
  76. /************************************************************************/
  77.  
  78. #ifndef STRLWR
  79. /**********************
  80. strlwr() converts a string to lowercase and returns a pointer to the string 
  81. */
  82. char *strlwr (str)
  83. char *str;
  84. {
  85.    register char *s;
  86.    s = str;
  87.    while (*s != '\0') {
  88.       *s = toascii(*s);
  89.       if (isupper(*s))
  90.          *s = tolower(*s);
  91.       s++;
  92.    }
  93.    return (str);
  94. }
  95. #endif /* STRLWR */
  96.  
  97. /**********************
  98. strcmpi() compares strings just like strcmp() but it does it without regard to
  99. case.
  100. */
  101. int strcmpi (s1, s2)
  102. register char *s1, *s2;
  103. {
  104.    for ( ; tolower(*s1) == tolower(*s2);  s1++, s2++)
  105.       if (*s1 == '\0')
  106.          return(0);
  107.    return(tolower(*s1) - tolower(*s2));
  108. }
  109.  
  110. #ifndef MEMSET
  111. /**********************
  112. memset() exists in Microsoft C and UNIX System V but not in Xenix.  It sets 
  113. the first "cnt" bytes of "dest" to the character "c" and returns a pointer to
  114. "dest".
  115. */
  116. char *memset (dest, c, cnt)
  117. char *dest;
  118. int c;
  119. unsigned cnt;
  120. {
  121.    register unsigned i;
  122.    for (i = 0; i < cnt; i++) {
  123.       *(dest + i) = c;
  124.    }
  125. }
  126. #endif /* MEMSET */
  127.  
  128. #ifndef FPUTCHAR
  129. /**********************
  130. fputchar() writes a character to stdout.  It is identical to putchar
  131. but is a function, not a macro.
  132. */
  133. int fputchar (c)
  134. int c;
  135. {
  136.    return (fputc(c, stdout));
  137. }
  138. #endif /* FPUTCHAR */
  139.  
  140. #ifndef TELL
  141. /**********************
  142. tell() returns the current position of the file handle supplied
  143. */
  144. long tell (handle)
  145. int handle;
  146. {
  147.    return (lseek (handle, 0L, 1));     /* seek to current position */
  148. }
  149. #endif /* TELL */
  150.  
  151. /***********************************************************************/
  152. /*** Following are declarations and functions that are written in a  ***/
  153. /*** machine-independent way but they implement machine-dependent    ***/
  154. /*** activities                                                      ***/
  155. /***********************************************************************/
  156.  
  157. #ifndef MSC
  158. /**********************
  159. to_long() converts four consecutive bytes, in order of increasing
  160. significance, to a long integer.  It is used to make Zoo independent of the
  161. byte order of the system.  
  162. */
  163. long to_long(data)
  164. BYTE data[];
  165. {
  166.    return (long) ((unsigned long) data[0] | ((unsigned long) data[1] << 8) |
  167.          ((unsigned long) data[2] << 16) | ((unsigned long) data[3] << 24));
  168. }
  169.  
  170. /********************
  171. splitlong() converts a long integer to four consecutive BYTEs in order
  172. of increasing significance.
  173. */
  174. void splitlong(bytes, bigword)
  175. BYTE bytes[];
  176. long bigword;
  177. {
  178.    int i;
  179.    for (i = 0; i < 4; i++) {
  180.       bytes[i] = bigword & 0xff;
  181.       bigword = (unsigned long) bigword >> 8;
  182.    }
  183. }     
  184.  
  185. /*******************
  186. splitint() converts an integer to two consecutive BYTEs in order
  187. of increasing significance.
  188. */
  189. void splitint(bytes, word)
  190. BYTE bytes[];
  191. int word;
  192. {
  193.    bytes[0] = word & 0xff;
  194.    word = (unsigned int) word >> 8;
  195.    bytes[1] = word & 0xff;
  196. }
  197.  
  198. /**********************
  199. to_int() converts two consecutive bytes, in order of increasing
  200. significance, to an integer, in a machine-independent manner
  201. */
  202. int to_int(data)
  203. BYTE data[];
  204. {
  205.    return (int) ((unsigned int) data[0] | ((unsigned int) data[1] << 8));
  206. }
  207.  
  208. #else /* else of ifndef MSC */
  209.  
  210. long to_long(data)
  211. BYTE data[];
  212. {
  213.    return ( * (long *) data );
  214. }
  215.  
  216. /********************
  217. splitlong() converts a long integer to four consecutive BYTEs in order
  218. of increasing significance.
  219. */
  220. void splitlong(bytes, bigword)
  221. BYTE bytes[];
  222. long bigword;
  223. {
  224.    * (long *) bytes = bigword;
  225. }     
  226.  
  227. /*******************
  228. splitint() converts an integer to two consecutive BYTEs in order
  229. of increasing significance.
  230. */
  231. void splitint(bytes, word)
  232. BYTE bytes[];
  233. int word;
  234. {
  235.    * (int *) bytes = word;
  236. }
  237.  
  238. /**********************
  239. to_int() converts two consecutive bytes, in order of increasing
  240. significance, to an integer.
  241. */
  242. int to_int(data)
  243. BYTE data[];
  244. {
  245.    return (*(int *) data);
  246. }
  247.  
  248. #endif /* ifndef MSC .. else ... */
  249.  
  250.  
  251. #ifndef FIZ
  252. /**********************
  253. Function frd_zooh() reads the header of a Zoo archive in a machine-
  254. independent manner, from a FILE.
  255. */
  256. int frd_zooh(zoo_header, zoo_file)
  257. struct zoo_header *zoo_header;
  258. FILE *zoo_file;
  259. {
  260.    int status;
  261.    BYTE bytes[SIZ_ZOOH];         /* canonical header representation */
  262. #ifdef DEBUG
  263.    if (verbose) {
  264.       printf("At file position [%8lx] ", ftell(zoo_file));
  265.    }
  266. #endif
  267.    status = fread ((char *) bytes, 1, SIZ_ZOOH, zoo_file);
  268.    b_to_zooh (zoo_header, bytes);   /* convert array to structure */
  269. #ifdef DEBUG
  270.    if (verbose) {
  271.       printf("frd_zooh: reading\n");
  272.       show_h(zoo_header);
  273.    }
  274. #endif
  275.    if (status < SIZ_ZOOH)
  276.       return (-1);
  277.    else
  278.       return (0);
  279. }
  280. #endif /* ifndef FIZ */
  281.  
  282.  
  283. /**********************
  284. Function frd_dir() reads a directory entry in a machine-independent manner,
  285. from a FILE.
  286. */
  287. int frd_dir(direntry, zoo_file) 
  288. struct direntry *direntry; 
  289. FILE *zoo_file;
  290. {
  291.    int status;
  292.    BYTE bytes[MAXDIRSIZE];    /* big enough to hold variable part too */
  293.  
  294.    /* To simplify things, we read the maximum possible size of the
  295.    directory entry including the variable size and discard what is not
  296.    needed */
  297. #ifdef DEBUG
  298.    if (verbose) {
  299.       printf("At file position [%8lx] ", ftell(zoo_file));
  300.    }
  301. #endif
  302.    status = fread ((char *) bytes, 1, MAXDIRSIZE, zoo_file);
  303.    if (status < SIZ_DIR)
  304.       return (-1);
  305.    b_to_dir (direntry, bytes);
  306. #ifdef DEBUG
  307.    if (verbose) {
  308.       printf("frd_dir: reading\n");
  309.       show_dir(direntry);
  310.    }
  311. #endif
  312.    return (0);
  313. }
  314.  
  315. #ifndef FIZ
  316. /**********************
  317. Function rd_zooh() reads a Zoo archive header in a machine-dependent manner,
  318. from a file handle.
  319. */
  320. int rd_zooh (header, zoo_han)
  321. struct zoo_header *header;
  322. int zoo_han;
  323. {
  324.    int status;
  325.    BYTE bytes[SIZ_ZOOH];
  326. #ifdef DEBUG
  327.    if (verbose) {
  328.       printf("At file position [%8lx] ", tell(zoo_han));
  329.    }
  330. #endif
  331.    status = read (zoo_han, (char *) bytes, SIZ_ZOOH);
  332.    b_to_zooh (header, bytes);
  333. #ifdef DEBUG
  334.    if (verbose) {
  335.       printf("rd_zooh: reading\n");
  336.       show_h(header);
  337.    }
  338. #endif
  339.    return (status);
  340. }
  341.  
  342. /**********************
  343. Function rd_dir() reads a directory entry in a machine-independent manner
  344. from a handle.
  345. */
  346. int rd_dir(direntry, zoo_han)
  347. struct direntry *direntry;
  348. int zoo_han;
  349. {
  350.    int status;
  351.    BYTE bytes[MAXDIRSIZE];    /* big enough to hold variable part too */
  352.    /* To simplify things, we read the maximum possible size of the
  353.    directory entry including the variable size and discard what is not
  354.    needed */
  355. #ifdef DEBUG
  356.    if (verbose) {
  357.       printf("At file position [%8lx] ", tell(zoo_han));
  358.    }
  359. #endif
  360.    status = read (zoo_han, (char *) bytes, MAXDIRSIZE);
  361.    if (status < SIZ_DIR)
  362.       return (-1);
  363.    b_to_dir (direntry, bytes);
  364. #ifdef DEBUG
  365.    if (verbose) {
  366.       printf("rd_dir: reading\n");
  367.       show_dir(direntry);
  368.    }
  369. #endif
  370.    return (0);
  371. }
  372.  
  373. /***********************
  374. Function fwr_dir() writes a directory entry in a machine-independent manner
  375. to a FILE.  Return value is -1 on error, else 0.
  376. */
  377. int fwr_dir(direntry, zoo_file)
  378. struct direntry *direntry;
  379. FILE *zoo_file;
  380. {
  381.    int size;
  382.    BYTE bytes[MAXDIRSIZE];
  383.    assert (direntry->type <= 2);
  384.    size = dir_to_b (bytes, direntry);
  385. #ifdef DEBUG
  386.    if (verbose) {
  387.       printf("At file position [%8lx] ", ftell(zoo_file));
  388.       printf("fwr_dir: writing\n");
  389.       show_dir(direntry);
  390.    }
  391. #endif
  392.  
  393.    if (fwrite ((char *) bytes, 1, size, zoo_file) != size)
  394.       return (-1);
  395.    else
  396.       return (0);
  397. }
  398.  
  399. /***********************
  400. Function wr_dir() writes a directory entry in a machine-independent manner
  401. to a handle.  Return value is -1 on error else 0.
  402. */
  403. int wr_dir(direntry, zoo_han)
  404. struct direntry *direntry;
  405. int zoo_han;
  406. {
  407.    int size;
  408.    BYTE bytes[MAXDIRSIZE];
  409.    assert (direntry->type <= 2);
  410.    size = dir_to_b (bytes, direntry);
  411. #ifdef DEBUG
  412.    if (verbose) {
  413.       printf("At file position [%8lx] ", tell(zoo_han));
  414.       printf("wr_dir:  writing\n");
  415.       show_dir(direntry);
  416.    }
  417. #endif
  418.    if (write (zoo_han, (char *) bytes, size) != size)
  419.       return (-1);
  420.    else
  421.       return (0);
  422. }
  423.  
  424. /***********************
  425. Function wr_zooh() writes an archive header in a machine-independent manner
  426. to a handle.  Return value -1 if error else 0.
  427. */
  428. int wr_zooh(zoo_header, zoo_han)
  429. struct zoo_header *zoo_header;
  430. int zoo_han;
  431. {
  432.    BYTE bytes[SIZ_DIR];
  433.    zooh_to_b (bytes, zoo_header);
  434.    if (write (zoo_han, (char *) bytes, SIZ_ZOOH) != SIZ_ZOOH)
  435.       return (-1);
  436.    else
  437.       return (0);
  438. }
  439.  
  440. /***********************
  441. Function fwr_zooh() writes an archive header in a machine-independent manner
  442. to a FILE.  Return value is -1 if error else 0.
  443. */
  444. int fwr_zooh(zoo_header, zoo_file)
  445. struct zoo_header *zoo_header;
  446. FILE *zoo_file;
  447. {
  448.    BYTE bytes[SIZ_DIR];
  449.    zooh_to_b (bytes, zoo_header);
  450.    if (fwrite ((char *) bytes, 1, SIZ_ZOOH, zoo_file) != SIZ_ZOOH)
  451.       return (-1);
  452.    else
  453.       return (0);
  454. }
  455.  
  456. /***********************
  457. b_to_zooh() converts an array of BYTE to a zoo_header structure.
  458. */
  459. void b_to_zooh (zoo_header, bytes)
  460. struct zoo_header *zoo_header;
  461. BYTE bytes[];
  462. {
  463.    int i;
  464.    for (i = 0; i < SIZ_TEXT; i++)                     /* copy text */
  465.       zoo_header->text[i] = bytes[TEXT_I + i];
  466.    zoo_header->zoo_tag = to_long(&bytes[ZTAG_I]);     /* copy zoo_tag */
  467.    zoo_header->zoo_start = to_long(&bytes[ZST_I]);    /* copy zoo_start */
  468.    zoo_header->zoo_minus = to_long(&bytes[ZSTM_I]);
  469.    zoo_header->major_ver = bytes[MAJV_I];          /* copy versions */
  470.    zoo_header->minor_ver = bytes[MINV_I];
  471. }
  472.  
  473. /***********************
  474. zooh_to_b() converts a zoo_header structure to an array of BYTE.
  475. */
  476. void zooh_to_b (bytes, zoo_header)
  477. struct zoo_header *zoo_header;
  478. BYTE bytes[];
  479. {
  480.    int i;
  481.    for (i = 0; i < SIZ_TEXT; i++)                     /* copy text */
  482.       bytes[TEXT_I + i] = zoo_header->text[i];
  483.    splitlong (&bytes[ZTAG_I], zoo_header->zoo_tag);
  484.    splitlong (&bytes[ZST_I], zoo_header->zoo_start);
  485.    splitlong (&bytes[ZSTM_I], zoo_header->zoo_minus);
  486.    bytes[MAJV_I] =   zoo_header->major_ver;           /* copy versions */ 
  487.    bytes[MINV_I] =   zoo_header->minor_ver;
  488. } /* zooh_to_b() */
  489.  
  490. /************************
  491. dir_to_b() converts a directory entry structure to an array of BYTE.
  492. */
  493. int dir_to_b (bytes, direntry)
  494. struct direntry *direntry;
  495. BYTE bytes[];
  496. {
  497.    int i;
  498.    int cursize;
  499.    int fixsize;
  500.    splitlong(&bytes[DTAG_I], direntry->zoo_tag);
  501.    bytes[DTYP_I] = direntry->type ;
  502.    bytes[PKM_I] = direntry->packing_method ;
  503.    splitlong(&bytes[NXT_I], direntry->next);
  504.    splitlong(&bytes[OFS_I], direntry->offset);
  505.    splitint(&bytes[DAT_I], direntry->date);
  506.    splitint(&bytes[TIM_I], direntry->time);
  507.    splitint(&bytes[CRC_I], direntry->file_crc);
  508.    splitlong(&bytes[ORGS_I], direntry->org_size);
  509.    splitlong(&bytes[SIZNOW_I], direntry->size_now);
  510.    bytes[DMAJ_I] = direntry->major_ver;
  511.    bytes[DMIN_I] = direntry->minor_ver;
  512.    bytes[DEL_I] = direntry->deleted;
  513.    bytes[STRUC_I] = direntry->struc;
  514.    splitlong(&bytes[CMT_I], direntry->comment);
  515.    splitint(&bytes[CMTSIZ_I], direntry->cmt_size);
  516.    for (i = 0; i < FNM_SIZ; i++)
  517.       bytes[FNAME_I + i] = direntry->fname[i];
  518.    bytes[TZ_I] = NO_TZ;       /* assume unknown */
  519.    bytes[NAMLEN_I] = 0;
  520.    bytes[DIRLEN_I] = 0;
  521.  
  522.    cursize = SIZ_DIR;         /* to count size of directory */
  523.    fixsize = SIZ_DIR;         /* size of fixed part */
  524.    assert (direntry->type <= 2);
  525.    if (direntry->type == 2) { /* handle stuff relevant to type 2 */
  526.       cursize = SIZ_DIRL;
  527.       fixsize = SIZ_DIRL;
  528.       bytes[TZ_I] = direntry->tz;
  529.       assert(direntry->namlen < 256 && direntry->namlen >= 0);
  530.       if (direntry->namlen > 0 || direntry->dirlen > 0)
  531.          cursize += 2;        /* space for namlen and dirlen */
  532.       if (direntry->namlen > 0) {
  533.          bytes[NAMLEN_I] = direntry->namlen;
  534.          for (i = 0; i < direntry->namlen; i++)
  535.             bytes[LFNAME_I+i] = direntry->lfname[i];
  536.          cursize += direntry->namlen;
  537.       } 
  538.       assert(direntry->dirlen < 256 && direntry->dirlen >= 0);
  539.       if (direntry->dirlen > 0) {
  540.          bytes[DIRLEN_I] = direntry->dirlen;
  541.          for (i = 0; i < direntry->dirlen; i++)
  542.             bytes[cursize+i] = direntry->dirname[i];
  543.          cursize += direntry->dirlen;
  544.       }
  545.       splitint(&bytes[cursize], direntry->system_id);
  546.    }
  547.  
  548.    /* Total length of directory entry is now cursize. */
  549.    splitint(&bytes[VARDIRLEN_I], cursize - fixsize);
  550.    assert(cursize == 
  551.             ((bytes[DIRLEN_I] > 0 || bytes[NAMLEN_I] > 0) ? 2 : 0) +
  552.             fixsize + bytes[DIRLEN_I] + bytes[NAMLEN_I]
  553.          );
  554.  
  555.    /* Do CRC assuming CRC field is zero, and stuff CRC into field. */
  556.    splitint(&bytes[DCRC_I], 0);           /* fill with zeroes */
  557.    crccode = 0;
  558.    addbfcrc(bytes, cursize);              /* update CRC */
  559.    splitint(&bytes[DCRC_I], crccode);
  560.  
  561.    /* return total length of directory entry */
  562.    return (cursize);
  563.  
  564.  
  565. } /* dir_to_b() */
  566. #endif /* ifndef FIZ */
  567.  
  568. /* b_to_dir() converts bytes to directory entry structure.  The CRC of the
  569. directory bytes, if any, is checked and a zero or nonzero value is returned
  570. in direntry->dir_crc according as the check is good or bad */
  571.  
  572. void b_to_dir(direntry, bytes)
  573. struct direntry *direntry;
  574. BYTE bytes[];
  575. {
  576.    int i;
  577.    unsigned int savecrc;
  578.    direntry->zoo_tag = to_long(&bytes[DTAG_I]);
  579.    direntry->type = bytes[DTYP_I];
  580.    direntry->packing_method = bytes[PKM_I];
  581.    direntry->next = to_long(&bytes[NXT_I]);
  582.    direntry->offset = to_long(&bytes[OFS_I]);
  583.    direntry->date = to_int(&bytes[DAT_I]);
  584.    direntry->time = to_int(&bytes[TIM_I]);
  585.    direntry->file_crc = to_int(&bytes[CRC_I]);
  586.    direntry->org_size = to_long(&bytes[ORGS_I]);
  587.    direntry->size_now = to_long(&bytes[SIZNOW_I]);
  588.    direntry->major_ver = bytes[DMAJ_I];
  589.    direntry->minor_ver = bytes[DMIN_I];
  590.    direntry->deleted = bytes[DEL_I];
  591.    direntry->struc = bytes[STRUC_I];
  592.    direntry->comment = to_long(&bytes[CMT_I]);
  593.    direntry->cmt_size = to_int(&bytes[CMTSIZ_I]);
  594.    for (i = 0; i < FNM_SIZ; i++)
  595.       direntry->fname[i] = bytes[FNAME_I + i];
  596.  
  597.    /* start by assuming variable part is zero bytes */
  598.    direntry->var_dir_len = direntry->dir_crc    = 0;
  599.    direntry->namlen      = direntry->dirlen     = 0;
  600.    direntry->lfname[0]   = direntry->dirname[0] = '\0';
  601.    direntry->tz = NO_TZ;               /* assume unknown */
  602.    direntry->system_id = SYSID_NIX;    /* default system_id if not present */
  603.  
  604.    assert (direntry->type <= 2);
  605.    if (direntry->type == 2) {
  606.       direntry->var_dir_len = to_int(&bytes[VARDIRLEN_I]);
  607.       assert(direntry->var_dir_len <= MAXDIRSIZE);
  608.       if (direntry->var_dir_len > MAXDIRSIZE)
  609.          direntry->var_dir_len = MAXDIRSIZE;
  610.       direntry->tz = bytes[TZ_I];   
  611.       if (direntry->var_dir_len > 0)
  612.          direntry->namlen = bytes[NAMLEN_I];
  613.       if (direntry->var_dir_len > 1)
  614.          direntry->dirlen = bytes[DIRLEN_I];
  615.       for (i = 0; i < direntry->namlen; i++)
  616.          direntry->lfname[i] = bytes[LFNAME_I + i];
  617.       for (i = 0; i < direntry->dirlen; i++)
  618.          direntry->dirname[i] = bytes[DIRNAME_I + direntry->namlen + i];
  619.       if (direntry->var_dir_len > direntry->namlen + direntry->dirlen + 2) {
  620.          direntry->system_id = to_int(&bytes[DIRNAME_I+direntry->namlen+i]);
  621.       }
  622.       /* do CRC calculation */
  623.       savecrc = (unsigned int) to_int(&bytes[DCRC_I]);
  624.       crccode = 0;
  625.       splitint(&bytes[DCRC_I], 0);
  626.       addbfcrc(bytes, SIZ_DIRL + direntry->var_dir_len);
  627.       direntry->dir_crc = crccode - savecrc;
  628.    }
  629. }
  630.  
  631. #ifdef DEBUG
  632. /* dump contents of archive header */
  633. show_h (zoo_header)
  634. struct zoo_header *zoo_header;
  635. {
  636.    int i;
  637.    printf ("Header text:\n");
  638.    for (i = 0; i < SIZ_TEXT-1;  i++)   /* all but trailing ^Z */
  639.       putchar(zoo_header->text[i]);
  640.    putchar('\n');
  641.    printf ("zoo_tag = [%8lx] zoo_start = [%8lx] zoo_minus = [%8lx]\n",
  642.             zoo_header->zoo_tag, zoo_header->zoo_start, 
  643.             zoo_header->zoo_minus);
  644.    printf ("major_ver.minor_ver = [%d.%d]\n",
  645.             zoo_header->major_ver, zoo_header->minor_ver);
  646.    printf ("---------\n");
  647. }
  648.  
  649. /* dump contents of directory entry */
  650. show_dir (direntry)
  651. struct direntry *direntry;
  652. {
  653.    int i;
  654.    printf ("Directory entry for file [%s][%s]:\n",
  655.             direntry->fname, direntry->lfname);
  656.    printf ("tag = [%8lx] type = [%d] PM = [%d] Next = [%8lx] Offset = [%8lx]\n",
  657.             direntry->zoo_tag, (int) direntry->type, 
  658.             (int) direntry->packing_method, direntry->next, 
  659.             direntry->offset);
  660.    printf ("Orig size = [%ld] Size now = [%ld] dmaj_v.dmin_v = [%d.%d]\n",
  661.          direntry->org_size, direntry->size_now,
  662.          (int) direntry->major_ver, (int) direntry->minor_ver);
  663.    printf ("Struc = [%d] DEL = [%d] comment_offset = [%8lx] cmt_size = [%d]\n",
  664.          (int) direntry->struc, (int) direntry->deleted, direntry->comment,
  665.          direntry->cmt_size);
  666.    printf ("var_dir_len = [%d] TZ = [%d] dir_crc = [%4x]\n",
  667.             direntry->var_dir_len, (int) direntry->tz, direntry->dir_crc);
  668.    printf ("system_id = [%d]  dirlen = [%d]  namlen = [%d]\n", 
  669.             direntry->system_id, direntry->dirlen, direntry->namlen);
  670.    if (direntry->dirlen > 0)
  671.       printf ("dirname = [%s]\n", direntry->dirname);
  672.    printf ("---------\n");
  673. }
  674. #endif   /* DEBUG */
  675.  
  676. #endif   /* PORTABLE */
  677.